package com.rmiad.config;

import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.solon.integration.SaTokenInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import com.rmiad.controller.LoginController;
import lombok.extern.slf4j.Slf4j;
import org.noear.dami.Dami;
import org.noear.snack.ONode;
import org.noear.solon.Solon;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Init;

import java.io.IOException;
import java.util.*;

@Slf4j
@Configuration
public class SaTokenConfigure {

    /**
     * 无需登录的接口地址集合
     */
    private final List<String> NO_LOGIN_PATH_LIST = new ArrayList<>();

    // 初始化时注册监听器
    // 初始化时注册监听器
    @Init
    private void initDamiListener() {
        // 定义添加路径的topic
        String ADD_PATH_TOPIC = "add_no_login_path";
        // 定义移除路径的topic
        String REMOVE_PATH_TOPIC = "remove_no_login_path";

        // 监听添加路径的消息
        Dami.<String, String>bus().listen(ADD_PATH_TOPIC, path -> {
            if (!NO_LOGIN_PATH_LIST.contains(path.getContent())) {
                NO_LOGIN_PATH_LIST.add(path.getContent());
                log.info("Added path to NO_LOGIN_PATH_LIST: {}", path);
            }
        });

        // 监听移除路径的消息
        Dami.<String, String>bus().listen(REMOVE_PATH_TOPIC, path -> {
            if (NO_LOGIN_PATH_LIST.contains(path.getContent())) {
                NO_LOGIN_PATH_LIST.remove(path.getContent());
                log.info("Removed path from NO_LOGIN_PATH_LIST: {}", path);
            }
        });
    }

    /**
     * 初始化应用路由
     */
    private static void initRoutes() {
        // 登录相关路由
        Solon.app().add("/admin", LoginController.class);

        // 根路由重定向
        Solon.app().get("/", ctx -> {
            if (StpUtil.isLogin()) {
                ctx.redirect("index.html");
            } else {
                ctx.redirect("login.html");
            }
        });
    }

    /**
     * 获取无需登录的接口路径集合
     *
     * @return 无需登录的路径集合
     */
    private List<String> getNoLoginPaths() {
        if (NO_LOGIN_PATH_LIST.isEmpty()) {
            // 基础无需登录路径
            NO_LOGIN_PATH_LIST.add("/admin/login");
            NO_LOGIN_PATH_LIST.add("/sys/config");

            // doc文档免登录路径
            NO_LOGIN_PATH_LIST.add("/swagger-resources");
            NO_LOGIN_PATH_LIST.add("/swagger/*");

            // 聊天接口免登录
            NO_LOGIN_PATH_LIST.add("/ai/chat/*");

            // 静态资源放行路径
            Collections.addAll(NO_LOGIN_PATH_LIST,
                    "/",
                    "/static/**",
                    "/favicon.ico",
                    "/**.html",
                    "/**.js",
                    "/**.css",
                    "/**.png",
                    "/**.jpg",
                    "/**.gif");
        }
        return NO_LOGIN_PATH_LIST;
    }

    /**
     * 拦截器
     *
     * @return
     */
    @Bean(index = -100)
    public SaTokenInterceptor saTokenInit() throws IOException {
        // 初始化路由
        initRoutes();

        return new SaTokenInterceptor()
                // 指定 [拦截路由] 与 [放行路由]
                .addInclude("/**").setExcludeList(getNoLoginPaths())
                .setAuth(req -> {
                    SaRouter.match("/**", StpUtil::checkLogin);
                })
                // 异常处理函数：每次认证函数发生异常时执行此函数
                .setError(e -> {
                    return ONode.newObject().set("status", 401).set("msg", "请重新登录");
                });
    }

}
